/*******************************************************************
 *
 * Copyright (C), 2021-2022, LS, All rights reserved.
 *
 * Author      : 
 * Create Time : 2021-09-17
 * Version     : v0.1
 * Description : 
 *******************************************************************/
 
/*----------------------------Head file----------------------------*/
#include "string.h"
#include "osal_app.h"
#include "ls_ble_type.h"
#include "ls_ble_phy62xx.h"
#include "ls_ble_sdk_config.h"
#include "user_config.h"

#include "gapgattserver.h"


#define LS_BLE_PHY_LOG_EN  1
#if LS_BLE_PHY_LOG_EN
#include "ls_ble_log.h"
#define TAG                             "ble_phy"
#define LS_BLE_PHY_LOG(level, ...)      LS_BLE_LOG_PRINT(level, TAG, ##__VA_ARGS__)
#else
#define LS_BLE_PHY_LOG(level, ...)
#endif

/*----------------------------macro file---------------------------*/

/*----------------------------type define--------------------------*/

/*----------------------------var define---------------------------*/							
volatile bool g_is_restart_adv = false;

static ls_ble_data_t s_scan_rsp =
{
    ADV_DATA_NO_DEV_NAME_LEN,
    {
        // flags
        0x02,
        GAP_ADTYPE_FLAGS,
        GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
        // service UUIDs
        0x03,
        GAP_ADTYPE_16BIT_MORE,
        LO_UINT16(CUSTOM_SERVICE_UUID),
        HI_UINT16(CUSTOM_SERVICE_UUID),
        // local name
        (BLE_ADV_DEV_NAME_LEN+1),
        GAP_ADTYPE_LOCAL_NAME_COMPLETE,
        //DEVICE_NAME_ARRAY			//We fill this array in function.
    }
};


static ls_ble_data_t s_adv_data =
{
    (ADV_MANUFACTORY_DATA_LEN+1),
    {
        ADV_MANUFACTORY_DATA_LEN,
        GAP_ADTYPE_MANUFACTURER_SPECIFIC,
        ADV_INIT_MANU_COMPANY_DATA
    }
};

/*-------------------------func declaration------------------------*/

/*-----------------------------------------------------------------*/


uint16_t ls_ble_init(void)
{
    return LS_BLE_SUCCESS;
}


uint16_t ls_ble_start_adv(void)
{
    if((gapProfileState == GAPROLE_STARTED) 
        || (gapProfileState == GAPROLE_WAITING) 
        || gapProfileState == GAPROLE_WAITING_AFTER_TIMEOUT)
    {
        uint8_t adv_enable = TRUE;
        GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &adv_enable);
        
        LS_BLE_PHY_LOG(LOG_LVL_DEBUG, "adv start");
        return LS_BLE_SUCCESS;
    }
    else {
        LS_BLE_PHY_LOG(LOG_LVL_DEBUG, "adv start invalid state");
        return LS_BLE_ERR_INVALID_STATE;
    }
}

uint16_t ls_ble_stop_adv(void)
{
    if(gapProfileState == GAPROLE_ADVERTISING) {
        uint8_t adv_enable = FALSE;
        GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &adv_enable);
        LS_BLE_PHY_LOG(LOG_LVL_DEBUG, "adv stop");
        return LS_BLE_SUCCESS;
    }
    else {
        LS_BLE_PHY_LOG(LOG_LVL_WARNING, "adv stop invalid state");
        return LS_BLE_ERR_INVALID_STATE;
    }
}


uint16_t ls_ble_disconnect(void)
{
    return GAPRole_TerminateConnection();
}


uint16_t ls_ble_set_mac(const ls_ble_mac_t* p_mac)
{
    if(LS_BLE_SUCCESS == ls_ble_stop_adv()) {
        g_is_restart_adv = true;
    }
    
    volatile uint8_t* p_ownPublicAddr = (volatile uint8_t*)0x1fff0965;  // It's 0x1fff0965 for 6222.
    memcpy((void*)p_ownPublicAddr, p_mac->addr, 6);
    
    return LS_BLE_SUCCESS;
}

uint16_t ls_ble_get_mac(ls_ble_mac_t* p_mac)
{
    volatile uint8_t* p_ownPublicAddr = (volatile uint8_t*)0x1fff0965;  // It's 0x1fff0965 for 6222.
    memcpy(p_mac->addr, (void*)p_ownPublicAddr, 6);
    return LS_BLE_SUCCESS;
}


uint16_t ls_ble_set_device_name(const uint8_t* buf, uint16_t size)
{
    GGS_SetParameter(GGS_DEVICE_NAME_ATT, size, (void*)buf);
    return 0;
}

uint16_t ls_ble_get_device_name(uint8_t* buf, uint16_t* p_size)
{
    *p_size = GAP_DEVICE_NAME_LEN;
    GGS_GetParameter(GGS_DEVICE_NAME_ATT, (void*)buf);
    return 0;
}


uint16_t ls_ble_set_advdata(const ls_ble_data_t* p_adv_data)
{
    if(LS_BLE_SUCCESS == ls_ble_stop_adv()) {
        g_is_restart_adv = true;
    }

    if(p_adv_data != NULL) {
        if(p_adv_data->len > 31) {
            return LS_BLE_ERR_INVALID_LENGTH;
        } else {
            s_adv_data.len = p_adv_data->len;
            osal_memcpy(s_adv_data.value, p_adv_data->value, p_adv_data->len);
            GAPRole_SetParameter(GAPROLE_ADVERT_DATA, s_adv_data.len, s_adv_data.value);
        }
    }

    return LS_BLE_SUCCESS;
}

uint16_t ls_ble_set_scanrsp(const ls_ble_data_t* p_scan_rsp)
{
    if(ls_ble_stop_adv() == 0) {
        g_is_restart_adv = true;
    }

    if(p_scan_rsp != NULL) {
        if(p_scan_rsp->len > 31) {
            return LS_BLE_ERR_INVALID_LENGTH;
        } else {
            s_scan_rsp.len = p_scan_rsp->len;
            osal_memcpy(s_scan_rsp.value, p_scan_rsp->value, p_scan_rsp->len);
            GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, s_scan_rsp.len, s_scan_rsp.value);
        }
    }
    return LS_BLE_SUCCESS;
}


uint16_t ls_ble_set_adv_param(const ls_ble_adv_param_t* p_param)
{
    if(LS_BLE_SUCCESS == ls_ble_stop_adv()) {
        g_is_restart_adv = true;
    }

    uint16 adv_interval_max = p_param->adv_interval_max*8/5;
    uint16 adv_interval_min = p_param->adv_interval_min*8/5;
    GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MIN, adv_interval_min);
    GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MAX, adv_interval_max);
    GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, adv_interval_min);
    GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, adv_interval_max);
    
    uint8 advType = LL_ADV_CONNECTABLE_UNDIRECTED_EVT;
    GAPRole_SetParameter(GAPROLE_ADV_EVENT_TYPE, sizeof( uint8 ), &advType);
    
    uint8 advChnMap = GAP_ADVCHAN_37 | GAP_ADVCHAN_38 | GAP_ADVCHAN_39;
    GAPRole_SetParameter(GAPROLE_ADV_CHANNEL_MAP, sizeof(uint8), &advChnMap);
    
    return LS_BLE_SUCCESS;
}


uint16_t ls_ble_set_conn_param(uint16_t cMin, uint16_t cMax, uint16_t latency, uint16_t timeout)
{
    //uint8 enable_update_request = TRUE;
    uint16_t desired_min_interval = cMin;
    uint16_t desired_max_interval = cMax;
    uint16_t desired_slave_latency = latency;
    uint16_t desired_conn_timeout = timeout;
    uint8_t  update_request = TRUE;
    //GAPRole_SetParameter( GAPROLE_PARAM_UPDATE_ENABLE, sizeof( uint8 ), &enable_update_request );
    GAPRole_SetParameter( GAPROLE_MIN_CONN_INTERVAL, sizeof( uint16 ), &desired_min_interval );
    GAPRole_SetParameter( GAPROLE_MAX_CONN_INTERVAL, sizeof( uint16 ), &desired_max_interval );
    GAPRole_SetParameter( GAPROLE_SLAVE_LATENCY, sizeof( uint16 ), &desired_slave_latency );
    GAPRole_SetParameter( GAPROLE_TIMEOUT_MULTIPLIER, sizeof( uint16 ), &desired_conn_timeout );
    GAPRole_SetParameter( GAPROLE_PARAM_UPDATE_REQ, sizeof( uint8 ), &update_request );

    return LS_BLE_SUCCESS;
}



uint16_t ls_ble_set_local_name(uint8_t* name, uint8_t len)
{
    if(name != NULL && len > 0) {
        s_scan_rsp.len = ADV_DATA_NO_DEV_NAME_LEN + len;
        s_scan_rsp.value[7] = len + 1;
        osal_memcpy(&s_scan_rsp.value[ADV_DATA_NO_DEV_NAME_LEN], name, len);
        GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, s_scan_rsp.len, s_scan_rsp.value);
    }

    return LS_BLE_SUCCESS;
}
 
uint16_t ls_ble_set_manufac_data(uint8_t* p_data, uint8_t len)
{
#if(LEIJISHU == 0)
    if(p_data != NULL && len > 0 && len <= (ADV_MANUFACTORY_DATA_LEN+1)) {
        osal_memcpy(s_adv_data.value, p_data, len);
        GAPRole_SetParameter(GAPROLE_ADVERT_DATA, s_adv_data.len, s_adv_data.value);
        return LS_BLE_SUCCESS;
    }
#else
    if(p_data != NULL && len > 0 && len <= ADV_DATA_MAX_LEN) {
        osal_memcpy(s_adv_data.value, p_data, len);
        GAPRole_SetParameter(GAPROLE_ADVERT_DATA, s_adv_data.len, s_adv_data.value);
        return LS_BLE_SUCCESS;
    }
#endif
    return LS_BLE_ERR_INVALID_PARAM;
}

uint16_t ls_ble_get_manufac_data(uint8_t* p_data, uint8_t len)
{
    if(p_data != NULL) {
        osal_memcpy(p_data, s_adv_data.value, len);
        return LS_BLE_SUCCESS;
    }
    return LS_BLE_ERR_INVALID_PARAM;
}
